package visualization.renderers
{
	import flash.display.LineScaleMode;
	import flash.events.Event;
	
	import mx.controls.Label;
	import mx.events.CollectionEvent;
	
	import visualization.IDataPoint;
	import visualization.Visualization;
	
	public class TwoDimensional extends OneDimensional
	{
		public var yAxis:Object;
		public var yMax:Object = 0;
		public var yMin:Object = 0;
		public var numberOfTicks:Object = 5;
		public var tickLength:Object = 5;
		
		private var _curentVisualization:Visualization = null
		
		public function TwoDimensional()
		{
			super();
		}
		
		override public function renderFull(source:Visualization):void{
			if(this._curentVisualization == null){
				this._curentVisualization = source;
				this._curentVisualization.addEventListener(CollectionEvent.COLLECTION_CHANGE,this.sort);
			}
			source.background.graphics.clear();
			source.resetLabels();
			var lineColor:uint = source.getValue(this.lineColor) as Number;
			source.background.graphics.lineStyle(source.getValue(this.lineThickness) as Number,lineColor,1,false,LineScaleMode.NORMAL,"none");
			
			var layout:Array = this.getLayout(source);
			
			// Render tick marks
			source.background.graphics.lineStyle(1,0,1);
			source.background.graphics.moveTo(0,source.height-1);
			source.background.graphics.lineTo(source.width-1,source.height-1);
			source.background.graphics.moveTo(0,0);
			source.background.graphics.lineTo(0,source.height-1);
			var ticks:Number = source.getValue(this.numberOfTicks) as Number;
			var tickL:Number = source.getValue(this.tickLength) as Number;
			var i:Number;
			var incr:Number = source.height/ticks;
			var tickLab:Label;
			var max:Number = this._pixelsPerY*source.height;
			for(i = source.height-1; i>0; i-=incr){
				source.background.graphics.moveTo(0,i);
				source.background.graphics.lineTo(tickL,i);
				tickLab = source.getLabel();
				tickLab.x = 0;
				tickLab.y = i-14;
				tickLab.text = (this._minY + (max-this._pixelsPerY*i)).toString();
			}
			incr = source.width/ticks;
			max = this._pixelsPerX*source.width;
			for(i = source.width-1; i>0; i-=incr){
				source.background.graphics.moveTo(i,source.height-1);
				source.background.graphics.lineTo(i,source.height-tickL);
				tickLab = source.getLabel();
				tickLab.x = i;
				tickLab.y = source.height-15;
				tickLab.text = (this._minX + (max-this._pixelsPerX*i)).toString();
			}
			
			
			// Plot points
			var last:Object = null;
			for each(var point:Object in layout){
				var element:IDataPoint = point.item as IDataPoint;
				
				element.x = point.x-point.width/2;
				element.y = point.y-point.height/2;
				element.width = point.width;
				element.height = point.height;
				element.toolTip = point.text;
				
				// Render Point
				if(element is Visualization){
					(element as Visualization).renderThubmnail();
				}
				else{
					element.graphics.beginFill(point.color);
					element.graphics.drawCircle(element.width/2,element.height/2,element.width/2);
				}
				
				// Render Line
				if(last != null){
					source.background.graphics.moveTo(last.x, last.y);
					source.background.graphics.lineTo(point.x, point.y);
				}
				
				last = point;
			}
		}
		
		override public function renderThumbnail(source:Visualization):void{
			if(this._curentVisualization == null){
				this._curentVisualization = source;
				this._curentVisualization.addEventListener(CollectionEvent.COLLECTION_CHANGE,this.sort);
			}
			source.background.graphics.clear();
			var lineColor:uint = source.getValue(this.lineColor) as Number;
			source.background.graphics.lineStyle(source.getValue(this.lineThickness) as Number,lineColor,1,false,LineScaleMode.NORMAL,"none");
			
			
			// Plot points
			var last:Object = null;
			for each(var point:Object in this.getLayout(source)){
				
				// Render Line
				if(last != null){
					source.background.graphics.moveTo(last.x, last.y);
					source.background.graphics.lineTo(point.x, point.y);
				}
				
				last = point;
			}
		}
		
		
		private var _pixelsPerX:Number;
		private var _pixelsPerY:Number;
		private var _minX:Number;
		private var _minY:Number;
		override public function getLayout(source:Visualization):Array{
			var layout:Array = new Array;
			this._minX = source.getValue(this.xMin) as Number;
			var xMaxn:Number = source.getValue(this.xMax) as Number;
			this._pixelsPerX = source.width/(xMaxn - this._minX);
			this._minY = source.getValue(this.yMin) as Number;
			var yMaxn:Number = source.getValue(this.yMax) as Number;
			this._pixelsPerY = source.height/(yMaxn - this._minY);
			for each(var point:IDataPoint in source.dataPoints){
				var size:Number = source.getValue(this.elementSize, point) as Number;
				var xAxisValue:Number = source.getValue(this.xAxis, point) as Number;
				var yAxisValue:Number = source.getValue(this.yAxis, point) as Number;
				layout.push({
					item:point,
					x:((xAxisValue - this._minX) * this._pixelsPerX),
					y:(source.height - (yAxisValue-this._minY) * this._pixelsPerY),
					width:size,
					height:size,
					color:(source.getValue(this.elementColor, point) as Number),
					text:(source.getValue(this.toolTip, point) as String)
					});
			}
			return layout;
		}
		
		override public function clone():VisualizationRenderer{
			var newVis:TwoDimensional = new TwoDimensional();
			this.initClone(newVis);
			return newVis;
		}
		
		override protected function initClone(rend:VisualizationRenderer):void{
			(rend as TwoDimensional).yAxis = this.yAxis;
			(rend as TwoDimensional).yMax = this.yMax;
			(rend as TwoDimensional).yMin = this.yMin;
			super.initClone(rend);
		}
		
		public function sort(event:Event = null):void{
			if(this._curentVisualization != null) this._curentVisualization.dataPoints.sort(this.sorting);
		}
		
		private function sorting( a:Object, b:Object ):int{
			var xa:Object = (a as IDataPoint).getData(this.xAxis);
			var xb:Object = (a as IDataPoint).getData(this.xAxis);
			if(xa == xb) return 0;
			else if(xa < xb) return -1;
			else return 1;
		}
	}
}